package com.bookmngsys.controller;

import com.alipay.api.kms.aliyun.http.HttpResponse;
import com.bookmngsys.View.*;
import com.bookmngsys.dao.BookLocationDao;
import com.bookmngsys.dao.CategoryDao;
import com.bookmngsys.entity.*;
import com.bookmngsys.service.BookInfoService;
import com.bookmngsys.service.BookService;
import com.bookmngsys.service.ReservationService;
import com.bookmngsys.utils.CommonUtils;
import com.bookmngsys.utils.Response;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.checkerframework.checker.units.qual.A;
import org.hibernate.annotations.AttributeAccessor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.ClassUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import javax.servlet.http.HttpServlet;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;



/**
 * @author Newway
 */
@Api("书籍管理")
@Controller
@RequestMapping("/api/book")
public class BookController {
    @Autowired
    BookService bookService;

    @Autowired
    BookInfoService bookInfoService;

    @Autowired
    ReservationService reservationService;
    @Autowired
    BookLocationDao bookLocationDao;



    @ApiOperation("查看预约图书")
    @GetMapping("/reserveBooks")
    @ResponseBody
    public Response reserveBooks(@RequestAttribute Integer readerId,HttpSession httpSession) {
        List<Reservation> reservations;
        try{

            reservations = reservationService.getReservationsByReaderId(readerId);

        }catch (Exception e){
            System.out.println(e.getStackTrace());
            return new Response().failure("预约错误");
        }
        return new Response().success(reservations);
    }


    @ApiOperation("预约图书")
    @GetMapping("/reserve")
    @ResponseBody
    public Response reserve(@RequestParam String isbn, @RequestAttribute Integer readerId,HttpSession httpSession) {
        try{
            reservationService.reserve(isbn,readerId);
        }catch (Exception e){
            System.out.println(e.getStackTrace());
            return new Response().failure(e.getMessage());
        }
        return new Response().success();
    }

    @ApiOperation("取消预约图书")
    @GetMapping("/cancelReserve")
    @ResponseBody
    public Response cancelReserve(@RequestParam int bookId,HttpSession httpSession) {
        try{
            reservationService.cancelReserve(bookId);
        }catch (Exception e){
            System.out.println(e.getStackTrace());
            return new Response().failure(e.getMessage());
        }
        return new Response().success();
    }

    @ApiOperation("获取书籍列表")
    @GetMapping("/getBooks")
    @ResponseBody
    public Response getBooks(@RequestParam Integer curPage, @RequestParam Integer pageSize, HttpSession httpSession) {
        UserDto userDto = (UserDto) httpSession.getAttribute("USER_SESSION");
        List<Book> books = bookService.getBooks(curPage, pageSize, userDto != null && userDto.isAdmin());
        return new Response().success(books.stream().map(BookDto::convertToBookDto));
    }


    @ApiOperation("获取书籍列表(包括bookid)")
    @GetMapping("/getBooksIncludeBookId")
    @ResponseBody
    public Response getBooksIncludeBookId(@RequestParam Integer curPage, @RequestParam Integer pageSize, HttpSession httpSession) {
        List<BookInfo> bookInfos = bookInfoService.getBooks();
        UserDto userDto = (UserDto) httpSession.getAttribute("USER_SESSION");
        List<Book> books = bookService.getBooks(curPage, pageSize, userDto != null && userDto.isAdmin());
        List<BookInfoDto> list = new ArrayList<>();

        for(BookInfo temp:bookInfos){
            BookInfoDto dto = new BookInfoDto();
            BookInfoDto bookInfoDto = dto.convertToBookDto(temp,books);
            list.add(bookInfoDto);
        }
        return new Response().success(list);
    }

    @ApiOperation("通过书名搜索")
    @GetMapping("/searchByBookName")
    @ResponseBody
    public Response searchByBookName(@RequestParam String bookName) {
        List<Book> books = bookService.searchByBookName(bookName);
        return new Response().success(books.stream().map(BookDto::convertToBookDto));
    }

    @ApiOperation("通过作者名搜索")
    @GetMapping("/searchByAuthor")
    @ResponseBody
    public Response searchByBookAuthor(@RequestParam String author) {
        List<Book> books = bookService.searchByAuthor(author);
        return new Response().success(books.stream().map(BookDto::convertToBookDto));
    }

    @ApiOperation("通过isbn搜索")
    @GetMapping("/searchByIsbn")
    @ResponseBody
    public Response searchByBookIsbn(@RequestParam String isbn) {
        List<Book> books = bookService.searchByIsbn(isbn);
        return new Response().success(books.stream().map(BookDto::convertToBookDto));
    }

    @ApiOperation("获取书籍详情")
    @GetMapping("/getBookDetail")
    @ResponseBody
    public Response getBook(@RequestParam String isbn) {
        Book book = bookService.getBook(isbn);
        return new Response().success(BookDto.convertToBookDto(book));
    }

//    @ApiOperation("借书")
//    @GetMapping("/borrowBook")
//    @ResponseBody
//    public Response borrowBook(@RequestParam String isbn, @RequestAttribute int userId, HttpSession httpSession) {
//        try {
//            reserve(isbn, userId, httpSession);
//            return borrowBookByReservation(isbn, userId);
//        } catch (Exception e) {
//            return new Response().failure(e.getMessage());
//        }
//    }
    @ApiOperation("直接借书")
    @GetMapping("/borrowBook")
    @ResponseBody
    public Response borrowBook(@RequestParam int bookId, @RequestParam int userId, HttpSession httpSession) {
        try {
            bookService.borrowBook(bookId, userId);
            return new Response().success();
        } catch (Exception e) {
            return new Response().failure(e.getMessage());
        }
    }

    @ApiOperation("多本书同时借书")
    @GetMapping("/borrowBooks")
    @ResponseBody
    public Response borrowBooks(@RequestParam String bookIdString, @RequestParam int userId, HttpSession httpSession) {
        try {
            String[] bookIds = bookIdString.split(",");
            for(String id:bookIds){
                int tempId = Integer.parseInt(id);
                bookService.borrowBook(tempId, userId);
            }
            return new Response().success();
        } catch (Exception e) {
            return new Response().failure(e.getMessage());
        }
    }

    @ApiOperation("预约借书")
    @GetMapping("/borrowBookByReservation")
    @ResponseBody
    @Deprecated
    public Response borrowBookByReservation(@RequestParam String isbn, @RequestParam int userId) {
        try {
            bookService.borrowBookByReserve(isbn, userId);
        } catch (Exception e) {
            return new Response().failure(e.getMessage());
        }
        return new Response().success();
    }

    @ApiOperation("续订")
    @GetMapping("/renew")
    @ResponseBody
    public Response renew(@RequestParam String isbn, @RequestParam int userId) {
        try {
            bookService.renew(isbn, userId);
        } catch (Exception e) {
            return new Response().failure(e.getMessage());
        }
        return new Response().success();
    }

    @ApiOperation("返还书籍")
    @GetMapping("/returnBook")
    @ResponseBody
    public Response returnBook(@RequestParam int bookId) {
        try {
            bookService.returnBook(bookId);
        } catch (Exception e) {
            return new Response().failure(e.getMessage());
        }
        return new Response().success();
    }

    @ApiOperation("还钱")
    @GetMapping("/payMoney")
    @ResponseBody
    public String payMoney(@RequestParam String out_trade_no, HttpServletResponse response) throws IOException {
        try {
            int bookId = Integer.parseInt(out_trade_no.substring(10));
            bookService.payMoney(bookId, out_trade_no);
        } catch (Exception e) {
//            return new Response().failure(e.getMessage());
            response.sendRedirect("http://localhost:3000/borrowBook");
            return "redirect:http://localhost:3000/borrowBook";
        }
        //return new Response().success();
        response.sendRedirect("http://localhost:3000/borrowBook");
        return "redirect:http://localhost:3000/borrowBook";

    }

    @ApiOperation("获取借书记录")
    @GetMapping("/getBorrowBooks")
    @ResponseBody
    public Response getBorrowBooks(@RequestAttribute int userId) {
        System.out.println("借书controller");
        List<BorrowBook> borrowBooks = bookService.getBorrowBooks(userId);
        return new Response().success(borrowBooks.stream().map(BorrowBookDto::convertToBorrowBookDto));
    }


    @ApiOperation("管理员获取借书记录(还书用)")
    @GetMapping("/getBorrowBooksByAdmin")
    @ResponseBody
    public Response getBorrowBooksByAdmin(@RequestParam Integer curPage, @RequestParam Integer pageSize) {
        System.out.println("管理员获取借书记录");
        List<BookInfo> borrowBookInfos = bookInfoService.getBooks();
        List<BookInfo> borrowBookInfosRes = new ArrayList<>();
        for(int i=0;i<borrowBookInfos.size();i++){
            if(borrowBookInfos.get(i).getBorrowReaderId()!=null){
                BookInfo bookInfo = borrowBookInfos.get(i);
                bookInfo.setFine(CommonUtils.getFineAmount(bookInfo.getReturnDate()));
                borrowBookInfosRes.add(bookInfo);
            }
        }
        return new Response().success(borrowBookInfosRes);
    }


    @ApiOperation("启用图书")
    @GetMapping("/enableBook")
    @ResponseBody
    public Response enableBook(@RequestParam String isbn, @RequestAttribute("user") UserDto userDto) {
        if (!userDto.isAdmin()) {
            return new Response().failure("当前用户没有权限");
        }
        bookService.enableBook(isbn);
        return new Response().success();
    }

    @ApiOperation("禁用图书")
    @GetMapping("/disableBook")
    @ResponseBody
    public Response disableBook(@RequestParam String isbn, @RequestAttribute("user") UserDto userDto) throws IllegalStateException, IOException {
        //按isbn借阅图书
        if (!userDto.isAdmin()) {
            return new Response().failure("当前用户没有权限");
        }
        bookService.disableBook(isbn);
        return new Response().success();
    }

    @ApiOperation("获取书籍分类")
    @GetMapping("/getCategory")
    @ResponseBody
    public Response getCategory() {
        List<Category> categories = bookService.getCategory();
        return new Response().success(categories);

    }
    @ApiOperation("删除书籍分类")
    @GetMapping("/deleteCategory")
    @ResponseBody
    public Response deleteCategory(@RequestParam int id) {
        try{
            bookService.deleteCategory(id);
        }catch (Exception e){
            return new Response().failure(e.getMessage());
        }
        return new Response().success();

    }
    @ApiOperation("新增书籍分类")
    @GetMapping("/addCategory")
    @ResponseBody
    public Response addCategory(@RequestParam String category) {
        bookService.addCategory(category);
        return new Response().success();
    }




    @ApiOperation("上传书籍")
    @PostMapping(value = "/uploadBook")
    @ResponseBody
    public Response uploadBook(@ModelAttribute BookDto bookDto,HttpSession httpSession) {
        Book existBook = bookService.getBook(bookDto.getIsbn());

//        if (existBook != null) {
//
//            return new Response().failure("该isbn号已存在");
//
//        }

        String imgUrl = bookDto.getImgUrl();
//        if (imgUrl != null) {
//            return saveFileAndResponse(file,bookDto);
//        }
        if (imgUrl == null) {
            return new Response().failure("上传图片错误");
        }
        bookDto.setImgUrl(imgUrl);
        int nums = bookDto.getAllNum();
        for(int i=0;i<nums;i++){
            try{
                bookInfoService.addBookToBookInfo(bookDto.getIsbn(),i+1,httpSession);
            }catch (Exception e){
                return new Response().failure("添加图书错误");
            }
        }
        bookService.addBook(BookDto.convertToBook(bookDto));
        return new Response().success();
    }

    @ApiOperation("下架书籍")
    @PostMapping(value = "/downLoadBook")
    @ResponseBody
    public Response downLoadBook(@RequestParam int bookid) {
        BookInfo existBook = bookInfoService.getBookById(bookid);

        if (existBook == null) {

            return new Response().failure("无此图书");

        }

        String isbn = existBook.getIsbn();

        bookInfoService.deleteBookByBookId(bookid);
        Book book =  bookService.getBook(isbn);
        book.setAllNum(book.getAllNum()-1);
        book.setAllNum(book.getLastNum()-1);
        bookService.addBook(book);

        return new Response().success();
    }



    @ApiOperation("更新书籍信息")
    @PostMapping(value = "/updateBook")
    @ResponseBody
    public Response updateBook(@RequestParam String originIsbn, @ModelAttribute BookDto bookDto, HttpSession httpSession) {
        try{
            bookService.updateBook(originIsbn, BookDto.convertToBook(bookDto), httpSession);
        }catch (Exception e){
            return new Response().failure("更新错误");
        }

        return new Response().success();
    }

    /**
     * 上传书籍图片
     * @param file
     * @return
     */
    private Response saveFileAndResponse(MultipartFile file,BookDto bookDto) {
        try{
            //前端通过：http://localhost:8080/img/aaa.pdf访问
            String originalName = file.getOriginalFilename();  //aaa.pdf
            String imgSuffix = originalName.substring(originalName.lastIndexOf(".")); //jpg
            String newName = UUID.randomUUID().toString() + imgSuffix;
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy/mm/dd");
            String datePath = sdf.format(new Date());
            File targetPath = new File("E://bookMng2022/" + datePath);
            if(!targetPath.exists()){
                targetPath.mkdirs(); //不存在，递归创建目录
            }
            File targetFileName = new File(targetPath,newName);
            file.transferTo(targetFileName);
            bookDto.setImgUrl(datePath + "/"+ newName);
            bookService.addBook(BookDto.convertToBook(bookDto));
            return new Response().success();
        } catch (IOException e) {
            e.printStackTrace();
            return new Response().failure("上传错误");
        }
    }





    @ApiOperation("获取违约通知通知")
    @GetMapping("/overdueNotification")
    @ResponseBody
    public Response getNotification(@RequestAttribute int userId) {
        NotificationDto notificationDto = new NotificationDto();
        notificationDto.setNum(bookService.getNumOfOverdue(userId));
        return new Response().success(notificationDto);
    }


//    @ApiOperation("获取剩余还书日期")
//    @GetMapping("/overdueNotification")
//    @ResponseBody
//    public Response getLastDayNotification(@RequestAttribute int userId, @RequestParam String isbn) {
//        List<BorrowBook> borrowBooks = bookService.getBorrowBooks(userId);
//        NotificationDto notificationDto = new NotificationDto();
//        for(BorrowBook borrowBook:borrowBooks){
//            if(borrowBook != null && System.currentTimeMillis() > borrowBook.getReturnDate().getTime()){
//                notificationDto.setLastDay(-1);
//            }
//            else if(borrowBook != null && borrowBook.getBook().getIsbn().equals(isbn)){
//                notificationDto.setLastDay(borrowBook.getReturnDate().getTime() - System.currentTimeMillis());
//            }
//        }
//        return new Response().success(notificationDto);
//    }

    @ApiOperation("获取书籍列表isbn(包括bookid)")
    @GetMapping("/getBooksIncludeBookIdByIsbn")
    @ResponseBody
    public Response getBooksIncludeBookIdByIsbn(@RequestParam String isbn, @RequestParam Integer curPage, @RequestParam Integer pageSize, HttpSession httpSession) {
        List<BookInfo> bookInfos = bookInfoService.getBooksByIsbn(isbn);
        List<TempDto> list = new ArrayList<>();
        for(BookInfo bookInfo: bookInfos){
            list.add(TempDto.convert(bookInfo));
        }
        return new Response().success(list);
    }


    @ApiOperation("删除图书ByIsbn")
    @GetMapping("/deleteBookByIsbn")
    @ResponseBody
    public Response deleteBookByIsbn(@RequestParam String isbn, @RequestAttribute("user") UserDto userDto) throws IllegalStateException, IOException {
        //按isbn借阅图书
        if (!userDto.isAdmin()) {
            return new Response().failure("当前用户没有权限");
        }try{
            bookService.deleteBookByIsbn(isbn);
        }catch (Exception e){
            return new Response().failure(e.getMessage());
        }

        return new Response().success();
    }

    @ApiOperation("删除图书byid")
    @GetMapping("/deleteBookByBookId")
    @ResponseBody
    public Response deleteBookByBookId(@RequestParam int bookId, @RequestAttribute("user") UserDto userDto) throws IllegalStateException, IOException {
        //按isbn借阅图书
        if (!userDto.isAdmin()) {
            return new Response().failure("当前用户没有权限");
        }try{
            bookService.deleteBookByBookId(bookId);
        }catch (Exception e){
            return new Response().failure(e.getMessage());
        }
        return new Response().success();
    }

    @ApiOperation("借阅管理通过readerid搜索")
    @GetMapping("/searchByReaderId")
    @ResponseBody
    public Response searchByReaderId(@RequestParam int readerId) {
        List<BookInfo> bookInfos = bookInfoService.searchByReaderId(readerId);
        return new Response().success(bookInfos);
    }

    @ApiOperation("管理员查看所有遗失图书")
    @GetMapping("/searchLostBooks")
    @ResponseBody
    public Response searchLostBooks() {
        List<BookInfo> bookInfos = bookInfoService.searchLostBooks();
        return new Response().success(bookInfos);
    }

    @ApiOperation("管理员查看所有损坏图书")
    @GetMapping("/searchDamageBooks")
    @ResponseBody
    public Response searchDamageBooks() {
        List<BookInfo> bookInfos = bookInfoService.searchDamageBooks();
        return new Response().success(bookInfos);
    }


    @ApiOperation("管理员设置遗失图书")
    @GetMapping("/setLostBook")
    @ResponseBody
    public Response setLostBook(@RequestParam int id,@RequestParam int status) {

        try{
            bookInfoService.setLostBook(id,status);
        }catch (Exception e){
            return new Response().failure(e.getMessage());
        }
        return new Response().success();
    }


    @ApiOperation("管理员设置损坏图书")
    @GetMapping("/setDamageBook")
    @ResponseBody
    public Response setDamageBook(@RequestParam int id,@RequestParam int status) {
        try{
            bookInfoService.setDamageBook(id,status);
        }catch (Exception e){
            return new Response().failure(e.getMessage());
        }
        return new Response().success();
    }


    @ApiOperation("获取书籍位置信息")
    @GetMapping("/getBookLocation")
    @ResponseBody
    public Response getBookLocation() {
        List<BookLocation> locations = bookService.getBookLocation();
        return new Response().success(locations);

    }
    @ApiOperation("删除书籍位置信息")
    @GetMapping("/deleteBookLocation")
    @ResponseBody
    public Response deleteBookLocation(@RequestParam String rackNumber) {
        try{
            bookService.deleteBookLocation(rackNumber);
        }catch (Exception e){
            return new Response().failure(e.getMessage());
        }
        return new Response().success();

    }
    @ApiOperation("新增书籍位置信息")
    @PostMapping("/addBookLocation")
    @ResponseBody
    public Response addBookLocation(@RequestBody BookLocation bookLocation) {
        try{
            if(bookLocation.getRackNumber()==null || bookLocation == null||bookLocation.getRackNumber()==""){
                throw new Exception("cannot be null");
            }
            bookService.addBookLocation(bookLocation);
        }catch (Exception e){
            return new Response().failure(e.getMessage());
        }
        return new Response().success();
    }

    @ApiOperation("更新书籍分类信息")
    @GetMapping("/updateCategory")
    @ResponseBody
    public Response updateCategory(@RequestParam int id,@RequestParam String category) {
        try{
            if(category==null){
                throw new Exception("cannot be null");
            }
            bookService.deleteCategory(id);
            bookService.addCategory(category);
        }catch (Exception e){
            return new Response().failure(e.getMessage());
        }
        return new Response().success();
    }

    @ApiOperation("更新书籍位置信息")
    @PostMapping("/updateBookLocation")
    @ResponseBody
    public Response updateBookLocation(@RequestBody BookLocation bookLocation) {
        try{
            if(bookLocation.getRackNumber()==null || bookLocation == null||bookLocation.getRackNumber()==""){
                throw new Exception("cannot be null");
            }
            bookLocation.setRackNumber("1");
            BookLocation bookLocation1 = bookLocationDao.findBookLocationByBookId("1");
            if(bookLocation.getCol()<bookLocation1.getCol()||
                    bookLocation.getFace()<bookLocation1.getFace() ||
                    bookLocation.getFloor()<bookLocation1.getFloor()||
                    bookLocation.getRow0()<bookLocation1.getRow0()){
                throw new Exception("cannot set");
            }
            bookService.deleteBookLocation(bookLocation.getRackNumber());
            bookService.addBookLocation(bookLocation);
        }catch (Exception e){
            return new Response().failure(e.getMessage());
        }
        return new Response().success();
    }
}
